	package com.mischa.doedeljas.client.ui;

import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.IOException;
import java.util.Collection;
import java.util.Vector;

import javax.swing.JButton;
import javax.swing.JPanel;
import javax.swing.JScrollPane;

import sun.misc.Compare;
import sun.misc.Sort;

import com.mischa.doedeljas.Card;
import com.mischa.doedeljas.Card.Suit;

public class CardsView extends JPanel implements ActionListener {
	/**
	 * 
	 */
	private static final long serialVersionUID = -1774592322977798598L;

	public interface SelectionChangedListener {		
		void selectionChanged(CardsView cardsView, Card selectedCard);
	}
	
	private volatile boolean updating = true;
	
	private Vector<Card> cards = new Vector<Card>();
	private SelectionChangedListener selectionListener = null;
	
	private Suit trumpSuit = null;
	private final Compare cardComparer = new Compare() {			
		@Override
		public int doCompare(Object first, Object second) {
			Card firstCard = (Card)first;
			Card secondCard = (Card)second;
						
			if(firstCard.equals(secondCard))
				return 0;
			// If the suits match, sort from high to low
			else if (firstCard.getSuit().equals(secondCard.getSuit()))
				return firstCard.exceeds(secondCard, trumpSuit) ? -1 : 1;
			// If the first is trump (and, if we got here, the second is not), it is higher
			else if (firstCard.getSuit().equals(trumpSuit))
				return -1;
			// If only the other second is trump, that is higher
			else if (secondCard.getSuit().equals(trumpSuit))
				return 1;
			// If the suits don't match, sort by suit
			else 
				return firstCard.getSuit().toInteger() - secondCard.getSuit().toInteger();
		}
	};	
		
	
	public CardsView()
	{
		
	}
	
	public void add(Collection<Card> cardsToAdd)
	{
		for(Card card : cardsToAdd)
		{
			addSingleCard(card);
		}
		sort();
		relayout();
	}
	
	public void add(Card cardToAdd)
	{		
		addSingleCard(cardToAdd);
		sort();
		relayout();
	}
	
	private void addSingleCard(Card cardToAdd)
	{	
		synchronized(cards)
		{
			cards.add(cardToAdd);
		}
	}
	
	public void remove(Card cardToRemove)
	{
		synchronized(cards)
		{
			cards.remove(cardToRemove);
		}
		
		relayout();
	}
	
	public void setTrumpSuit(Suit newTrumpSuit)
	{
		trumpSuit = newTrumpSuit;
		sort();
		relayout();
	}
	
	public void setSelectionChangedListener(SelectionChangedListener newSelectionChangedListener)
	{
		selectionListener = newSelectionChangedListener;
	}
	
	private void sort()
	{	
		Card[] cardArray = cards.toArray(new Card[] {});		
		Sort.quicksort(cardArray, cardComparer);
		
		synchronized(cards)
		{
			cards.clear();
			for(Card card : cardArray)
			{
				cards.add(card);
			}
		}
	}

	private void relayout()
	{
		if (!updating)
		{
			return;
		}
		
		removeAll();
		setLayout(new FlowLayout());
		
		synchronized(cards)
		{
			for(Card card : cards)
			{
				try {
					CardButton cardButton = new CardButton(card);
					cardButton.setActionListener(this);			
					add(cardButton);
				} catch (IOException e) {
					JButton cardButton = new JButton(card.toString());
					cardButton.addActionListener(this);			
					add(cardButton);
				}
			}
		}
		
		validate();
	}

	@Override
	public void actionPerformed(ActionEvent event) {
		if(selectionListener == null)
		{
			return;
		}
		
		CardButton source = (CardButton)event.getSource();
		selectionListener.selectionChanged(this, source.getCard());						
	}

	public void clear() {
		synchronized(cards)
		{
			cards.clear();
		}
		relayout();
	}
	
	public void suspendLayout() {
		updating = false;
	}
	
	public void resumeLayout() {
		updating = true;
		relayout();
	}

}
